package com.hzd.service;

import ablaze.framework.api.result.ExecuteResult;
import ablaze.framework.config.SystemConfig;
import ablaze.framework.constant.Constant;
import ablaze.framework.db.page.impl.mybatis.MyBatisPageConvertor;
import ablaze.framework.db.page.impl.mybatis.PageHelper;
import ablaze.framework.page.PageInfo;
import ablaze.framework.service.BaseService;
import ablaze.framework.utils.BigDecimalUtils;
import ablaze.framework.utils.RandomUtils;
import com.hzd.cache.JsApiTicketCache;
import com.hzd.condition.ActivityUserCondition;
import com.hzd.dao.ActivityUserDao;
import com.hzd.entity.*;
import com.hzd.sdk.api.SnsAPI;
import com.hzd.sdk.bean.SnsToken;
import com.hzd.sdk.util.JsUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.List;
import java.util.Random;

/**
 * 活动
 *
 * @author christ
 * @date 2015/10/20
 */
@Component
@Transactional
public class ActivityService extends BaseService {

    private static final String APPID_KEY = "wx.appid";
    private static final String SECRET_KEY = "wx.secret";

    @Autowired
    private ActivityUserDao activityUserDao;

    @Autowired
    private JsApiTicketCache jsApiTicketCache;

    //------------------------------------pc端----------------------------------------

    /**
     * 活动参加者查询
     *
     * @param pageIndex
     * @param pageSize
     * @param condition
     * @return
     */
    public PageInfo findActivityUserPagedList(Integer pageIndex, Integer pageSize, ActivityUserCondition condition) {

        PageHelper.startPage(pageIndex, pageSize, true);

        return MyBatisPageConvertor.getInstance().convert(activityUserDao.findActivityUsers(condition));
    }

    public PageInfo findRelayUserPagedList(Integer pageIndex, Integer pageSize, String fromOpenid) {

        PageHelper.startPage(pageIndex, pageSize, true);

        return MyBatisPageConvertor.getInstance().convert(activityUserDao.findRelayUsers(fromOpenid));
    }


    //------------------------------------手机端----------------------------------------

    /**
     * 获取OpenId
     *
     * @param code
     * @return
     */
    public String getOpenId(String code) {

        if (isEmpty(code)) {
            return null;
        }

        SnsToken snsToken = SnsAPI.oauth2AccessToken(SystemConfig.getString(APPID_KEY), SystemConfig.getString(SECRET_KEY), code);

        return snsToken.getOpenid();
    }

    /**
     * 页面config值
     *
     * @return
     */
    public String getJsConfig(String url) {

        String[] jsApis = new String[]{
                "onMenuShareTimeline",
                "onMenuShareAppMessage",
                "hideMenuItems"
        };

        return JsUtil.generateConfigJson(jsApiTicketCache.getTicket(), false, SystemConfig.getString(APPID_KEY), url, jsApis);
    }

    /**
     * 生成授权url
     *
     * @param url
     * @param state
     * @return
     */
    public String getShareUrl(String url, String state) {

        return SnsAPI.connectOauth2Authorize(SystemConfig.getString(APPID_KEY), url, false, state);
    }


    /**
     * 参与活动
     *
     * @return
     */
    public ExecuteResult participate(ActivityUser user) {

        if (isEmpty(user.getOpenid()) || isEmpty(user.getNickName()) || isEmpty(user.getMobile())) {
            return failParamNull();
        }

        if (isNotMoblie(user.getMobile())) {
            return failParamInvalidate("请输入正确的手机号");
        }

        if (duplicated(user, "openid")) {
            return failParamInvalidate("您已参加该活动，不能重复参加");
        }

        return success(storeAndQuery(user));
    }

    /**
     * 判断用户是否已做租房申请
     *
     * @param openid
     * @return
     */
    public ExecuteResult hasApplyed(String openid) {

        if (isEmpty(openid)) {
            return failParamNull("请在微信浏览器中打开");
        }

        List<Tenant> tenants = findUseable(Tenant.class)
                .where()
                .eq("openid", openid)
                .findList();

        if (isEmpty(tenants)) {
            return failDataNotExist();
        }

        return success();
    }

    /**
     * 判断用户是否接力
     *
     * @param user
     * @return
     */
    /*public ExecuteResult hasRelayed(RelayUser user) {

        if (isEmpty(user.getOpenid()) || isEmpty(user.getFromOpenid())) {
            return failParamNull();
        }

        RelayUser stored = getRelayUser(user.getFromOpenid(), user.getOpenid());

        if (isEmpty(stored)) {
            return failDataNotExist("您还没有为该用户接力");
        }

        return success().setResultMsg("您已经为该用户接力，分享本页面可让其他人为该用户接力");
    }*/

    /**
     * 接力
     *
     * @param user
     * @return
     */
    public ExecuteResult relay(RelayUser user) {

        ExecuteResult result = validateBeforeRelay(user);

        if (result.fail()) {

            return result;
        }

        // 保存接力用户
        store(user);

        //现在点击接力按钮就算接力成功
        //递增接力人数和奖励
        relayCountAndBondAmountIncrease(user.getFromOpenid(), user.getOpenid());

        //返回数据
        return success(main(user.getFromOpenid()).getResultData());

    }

    /**
     * 分享以后更新接力用户的分享状态
     *
     * @param user
     * @return
     */
    public ExecuteResult afterShare(RelayUser user) {

        if (isEmpty(user.getOpenid()) || isEmpty(user.getFromOpenid())) {
            return failParamNull();
        }

        RelayUser stored = getRelayUser(user.getFromOpenid(), user.getOpenid());

        if (isEmpty(stored)) {
            return failParamInvalidate("您还没有为该用户接力，请接力后分享");
        }

        //未分享
        if (stored.getIsShare().equals(Constant.BOOLEAN.N)) {
            stored.setIsShare(Constant.BOOLEAN.Y);
            store(stored);

            //递增接力人数和奖励
            relayCountAndBondAmountIncrease(user.getFromOpenid(), stored.getOpenid());

            //返回数据
            return success(main(user.getFromOpenid()).getResultData());
        }

        return failDataDuplicated();

    }

    /**
     * 领奖励
     *
     * @param openid
     * @return
     */
    public ExecuteResult claimBond(String openid) {

        ExecuteResult result = validateBeforeClaim(openid);

        if (result.fail()) {
            return result;
        }

        //更新奖励状态
        //updateBondClaimed(openid);

        ExecuteResult applyResult = hasApplyed(openid);
        //已做租+申请
        if (applyResult.success()) {
            updateBondClaimed(openid);
            //已做过租+申请的自定义code--表示已申请租+,区别于其它的错误编码
            return success().setResultCodeExt(8888);
        }

        return success();
    }

    /**
     * 奖励更新为已领取状态
     *
     * @param openid
     */
    private void updateBondClaimed(String openid) {
        ActivityUserBond bond = getBond(openid);
        bond.setIsClaimed(Constant.BOOLEAN.Y);
        store(bond);
    }


    /**
     * 打开主页面
     *
     * @param openid
     * @return
     */
    public ExecuteResult main(String openid) {

        if (isEmpty(openid)) {
            return failParamNull();
        }

        ActivityUser user = getActivityUserByOpenid(openid);

        if (isEmpty(user)) {
            return failDataNotExist("您尚未参加该活动");
        }

        String shareDesc = "你租房，我交租！疯狂接力，抢互助金服租+房租抵用券，最高可抵万元房租";

        //接力用户小于10
        if (user.getCount() < 10) {
            return success(
                    toMap("my", user, "isRank", false, "shareDesc", shareDesc)
            );
        }

        //超过10人
        ActivityUserBond bond = getBond(openid);
        shareDesc = "我是" + user.getNickName() + ",正在参加租+『我向房东打白条』活动,已经有亲友帮我打了" + bond.getAmount() + "元白条,快来帮我接力吧,么么哒!";
        return success(
                toMap("my", user, "isRank", true, "bond", bond, "shareDesc", shareDesc)
        );
    }

    /**
     * 接力前校验
     *
     * @param user
     * @return
     */
    public ExecuteResult validateBeforeRelay(RelayUser user) {

        if (isEmpty(user.getOpenid()) || isEmpty(user.getFromOpenid())) {
            return failParamNull();
        }

        if (user.getFromOpenid().equals(user.getOpenid())) {
            return failParamInvalidate("亲，不能为自己接力哦");
        }

        RelayUser relayUser = getRelayUser(user.getFromOpenid(), user.getOpenid());

        /*if (isNotEmpty(relayUser)) {

            if (Constant.BOOLEAN.Y.equals(relayUser.getIsShare())) {
                return failParamInvalidate("您已为该用户接力过,不能重复接力!");
            }

            if (Constant.BOOLEAN.N.equals(relayUser.getIsShare())) {
                return failDataDuplicated();
            }
        }*/

        if (isNotEmpty(relayUser)){
            return failParamInvalidate("您已为该用户接力过,不能重复接力!");
        }

        return success();
    }

    /**
     * 领取奖励前校验
     *
     * @param openid
     * @return
     */
    public ExecuteResult validateBeforeClaim(String openid) {

        if (isEmpty(openid)) {
            return failParamNull();
        }

        ActivityUser storedUser = getActivityUserByOpenid(openid);

        if (isEmpty(storedUser)) {
            return failDataNotExist("您尚未参加该活动");
        }

        if (storedUser.getCount() < 10) {
            return failParamInvalidate("您的接力用户不满10个，继续加油哦");
        }

        ActivityUserBond bond = getBond(openid);

        if (isEmpty(bond)) {
            return failDataNotExist("未找到相应的奖励!");
        }

        if (Constant.BOOLEAN.Y.equals(bond.getIsClaimed())) {
            return failParamInvalidate("您已领取该奖励");
        }

        return success();
    }

    /**
     * 获取当前完整url
     *
     * @param request
     * @return
     */
    public String getCurrentURL(HttpServletRequest request) {

        //return request.getRequestURL().toString();
        return request.getRequestURL() +
                (isEmpty(request.getQueryString()) ? "" : "?"+request.getQueryString());
    }


    //------------------------------------private----------------------------------------

    /**
     * 根据openid查找用户
     *
     * @param openid
     * @return
     */
    private ActivityUser getActivityUserByOpenid(String openid) {

        if (isEmpty(openid)) {
            return null;
        }

        return findUseable(ActivityUser.class)
                .where()
                .eq("openid", openid)
                .findUnique();
    }

    /**
     * 查询接力者
     *
     * @param fromOpenid
     * @param openid
     * @return
     */
    private RelayUser getRelayUser(String fromOpenid, String openid) {

        if (isEmpty(fromOpenid) || isEmpty(openid)) {
            return null;
        }

        return findUseable(RelayUser.class)
                .where()
                .eq("openid", openid)
                .eq("fromOpenid", fromOpenid)
                .findUnique();
    }

    /**
     * 查询奖励
     *
     * @param openid
     * @return
     */
    private ActivityUserBond getBond(String openid) {

        if (isEmpty(openid)) {
            return null;
        }

        return findUseable(ActivityUserBond.class)
                .where()
                .eq("openid", openid)
                .findUnique();
    }

    /**
     * 生成奖励
     *
     * @param openid
     */
    private void createBond(String openid) {

        store(new ActivityUserBond()
                        .setOpenid(openid)
                        .setBondCode(RandomUtils.randomAlpha(10))
                        .setAmount(new BigDecimal("60"))
        );
    }

    /**
     * 增加接力人数和奖励
     *
     * @param fromOpenid
     * @param relayOpenid
     */
    private void relayCountAndBondAmountIncrease(String fromOpenid, String relayOpenid) {
        if (isEmpty(fromOpenid)) {
            return;
        }

        ActivityUser activityUser = getActivityUserByOpenid(fromOpenid);

        if (isEmpty(activityUser)) {
            return;
        }

        //递增接力人数
        ActivityUser stored = storeAndQuery(activityUser.setCount(activityUser.getCount() + 1));

        //第十人生成奖励
        if (stored.getCount() == 10) {
            createBond(fromOpenid);
            return;
        }

        //多于10人的累加奖励
        if (stored.getCount() > 10) {

            ActivityUserBond bond = getBond(fromOpenid);

            //白条已领取后,分享不再增加奖励金额
            if (Constant.BOOLEAN.Y.equals(bond.getIsClaimed())) {
                return;
            }
            increaseBondAmount(fromOpenid, relayOpenid);
        }
    }

    /**
     * 累积奖励
     *
     * @param fromOpenid
     * @param relayOpenid
     */
    private void increaseBondAmount(String fromOpenid, String relayOpenid) {

        ActivityUserBond bond = getBond(fromOpenid);

        if (isEmpty(bond)) {
            return;
        }

        int randomInt = new Random().nextInt(100);

        int increaseStep = 0;
        if (randomInt >= 0 && randomInt < 40) {
            increaseStep = 1;
        } else if (randomInt >= 40 && randomInt < 70) {
            increaseStep = 2;
        } else if (randomInt >= 70 && randomInt < 85) {
            increaseStep = 3;
        } else if (randomInt >= 85 && randomInt < 95) {
            increaseStep = 5;
        } else if (randomInt >= 95 && randomInt <= 100) {
            increaseStep = 10;
        }

        //累加奖励
        bond.setAmount(bond.getAmount().add(new BigDecimal(increaseStep)));

        // 上限不超过5000
        if (BigDecimalUtils.compareTo(new BigDecimal(5000), bond.getAmount()) < 0) {
            bond.setAmount(new BigDecimal(5000));
        }

        store(bond);

        //记录
        store(new BondIncreaseLog().setStep(new BigDecimal(increaseStep)).setFromOpenid(fromOpenid).setOpenid(relayOpenid));
    }
}
